home *** CD-ROM | disk | FTP | other *** search
/ 130 MIDI Tool Box / 130 MIDI Tool Box.iso / midifile / midifile.c < prev    next >
C/C++ Source or Header  |  1989-03-05  |  11KB  |  565 lines

  1. /*
  2.  * Read a Standard MIDI File.  Externally-assigned function pointers are
  3.  * called upon recognizing things in the file.  See midifile(3).
  4.  */
  5.  
  6. #include "midi.h"
  7. #include "midifile.h"
  8.  
  9. #define EOF (-1)
  10.  
  11. #ifdef PROTOTYPES
  12. #define NOARGS VOID
  13. #else
  14. #define NOARGS
  15. #endif
  16.  
  17. #ifdef NOVOID
  18. #define VOID int
  19. #else
  20. #define VOID void
  21. #endif
  22.  
  23. /* public stuff */
  24.  
  25. /* Functions to be called while processing the MIDI file. */
  26. VOID (*Mf_starttrack)(NOARGS) = 0;
  27. VOID (*Mf_endtrack)(NOARGS) = 0;
  28. int (*Mf_getc)(NOARGS) = 0;
  29. VOID (*Mf_eot)(NOARGS) = 0;
  30. #ifdef PROTOTYPES
  31. VOID (*Mf_error)(char *) = 0;
  32. VOID (*Mf_header)(int,int,int) = 0;
  33. VOID (*Mf_on)(int,int,int) = 0;
  34. VOID (*Mf_off)(int,int,int) = 0;
  35. VOID (*Mf_pressure)(int,int,int) = 0;
  36. VOID (*Mf_controller)(int,int,int) = 0;
  37. VOID (*Mf_pitchbend)(int,int,int) = 0;
  38. VOID (*Mf_program)(int,int) = 0;
  39. VOID (*Mf_chanpressure)(int,int) = 0;
  40. VOID (*Mf_sysex)(int,char*) = 0;
  41. VOID (*Mf_arbitrary)(int,char*) = 0;
  42. VOID (*Mf_metamisc)(int,int,char*) = 0;
  43. VOID (*Mf_seqnum)(int) = 0;
  44. VOID (*Mf_smpte)(int,int,int,int,int) = 0;
  45. VOID (*Mf_timesig)(int,int,int,int) = 0;
  46. VOID (*Mf_tempo)(int) = 0;
  47. VOID (*Mf_keysig)(int,int) = 0;
  48. VOID (*Mf_sqspecific)(int,char*) = 0;
  49. VOID (*Mf_text)(int,int,char*) = 0;
  50. #else
  51. VOID (*Mf_error)() = 0;
  52. VOID (*Mf_header)() = 0;
  53. VOID (*Mf_on)() = 0;
  54. VOID (*Mf_off)() = 0;
  55. VOID (*Mf_pressure)() = 0;
  56. VOID (*Mf_controller)() = 0;
  57. VOID (*Mf_pitchbend)() = 0;
  58. VOID (*Mf_program)() = 0;
  59. VOID (*Mf_chanpressure)() = 0;
  60. VOID (*Mf_sysex)() = 0;
  61. VOID (*Mf_arbitrary)() = 0;
  62. VOID (*Mf_metamisc)() = 0;
  63. VOID (*Mf_seqnum)() = 0;
  64. VOID (*Mf_smpte)() = 0;
  65. VOID (*Mf_tempo)() = 0;
  66. VOID (*Mf_timesig)() = 0;
  67. VOID (*Mf_keysig)() = 0;
  68. VOID (*Mf_sqspecific)() = 0;
  69. VOID (*Mf_text)() = 0;
  70. #endif
  71.  
  72. int Mf_nomerge = 0;        /* 1 => continue'ed system exclusives are */
  73.                 /* not collapsed. */
  74. long Mf_currtime = 0L;        /* current time in delta-time units */
  75. int Mf_skipinit = 0;        /* 1 if initial garbage should be skipped */
  76.  
  77. /* private stuff */
  78.  
  79. static long Mf_toberead = 0L;
  80.  
  81. static long readvarinum(NOARGS);
  82. static long read32bit(NOARGS);
  83. static int read16bit(NOARGS);
  84. static VOID msgenlarge(NOARGS);
  85. static char *msg(NOARGS);
  86. static int readheader(NOARGS);
  87. static VOID readtrack(NOARGS);
  88. static VOID sysex(NOARGS), msginit(NOARGS);
  89. static int egetc(NOARGS);
  90. static int msgleng(NOARGS);
  91.  
  92. #ifdef PROTOTYPES
  93. static int readmt(char*,int);
  94. static long to32bit(int,int,int,int);
  95. static int to16bit(int,int);
  96. static VOID mferror(char *);
  97. static VOID badbyte(int);
  98. static VOID metaevent(int);
  99. static VOID msgadd(int);
  100. static VOID chanmessage(int,int,int);
  101. #else
  102. static long to32bit();
  103. static int to16bit();
  104. static VOID mferror();
  105. static VOID badbyte();
  106. static VOID metaevent();
  107. static VOID msgadd();
  108. static VOID chanmessage();
  109. #endif
  110.  
  111. VOID
  112. midifile()         /* The only non-static function in this file. */
  113. {
  114.     int ntrks;
  115.  
  116.     if ( Mf_getc == 0 )
  117.         mferror("mf.h() called without setting Mf_getc"); 
  118.  
  119.     ntrks = readheader();
  120.     if ( ntrks <= 0 )
  121.         mferror("No tracks!");
  122.     while ( ntrks-- > 0 )
  123.         readtrack();
  124. }
  125.  
  126. static int
  127. readmt(s,skip)        /* read through the "MThd" or "MTrk" header string */
  128. char *s;
  129. int skip;        /* if 1, we attempt to skip initial garbage. */
  130. {
  131.     int nread = 0;
  132.     char b[4];
  133.     char buff[32];
  134.     int c;
  135.     char *errmsg = "expecting ";
  136.  
  137.     retry:
  138.     while ( nread<4 ) {
  139.         c = (*Mf_getc)();
  140.         if ( c == EOF ) {
  141.             errmsg = "EOF while expecting ";
  142.             goto err;
  143.         }
  144.         b[nread++] = c;
  145.     }
  146.     /* See if we found the 4 characters we're looking for */
  147.     if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] )
  148.         return(0);
  149.     if ( skip ) {
  150.         /* If we are supposed to skip initial garbage, */
  151.         /* try again with the next character. */
  152.         b[0]=b[1];
  153.         b[1]=b[2];
  154.         b[2]=b[3];
  155.         nread = 3;
  156.         goto retry;
  157.     }
  158.     err:
  159.     (VOID) strcpy(buff,errmsg);
  160.     (VOID) strcat(buff,s);
  161.     mferror(buff);
  162.     return(0);
  163. }
  164.  
  165. static int
  166. egetc()            /* read a single character and abort on EOF */
  167. {
  168.     int c = (*Mf_getc)();
  169.  
  170.     if ( c == EOF )
  171.         mferror("premature EOF");
  172.     Mf_toberead--;
  173.     return(c);
  174. }
  175.  
  176. static int
  177. readheader()        /* read a header chunk */
  178. {
  179.     int format, ntrks, division;
  180.  
  181.     if ( readmt("MThd",Mf_skipinit) == EOF )
  182.         return(0);
  183.  
  184.     Mf_toberead = read32bit();
  185.     format = read16bit();
  186.     ntrks = read16bit();
  187.     division = read16bit();
  188.  
  189.     if ( Mf_header )
  190.         (*Mf_header)(format,ntrks,division);
  191.  
  192.     /* flush any extra stuff, in case the length of header is not 6 */
  193.     while ( Mf_toberead > 0 )
  194.         (VOID) egetc();
  195.     return(ntrks);
  196. }
  197.  
  198. static VOID
  199. readtrack()         /* read a track chunk */
  200. {
  201.     /* This array is indexed by the high half of a status byte.  It's */
  202.     /* value is either the number of bytes needed (1 or 2) for a channel */
  203.     /* message, or 0 (meaning it's not  a channel message). */
  204.     static int chantype[] = {
  205.         0, 0, 0, 0, 0, 0, 0, 0,        /* 0x00 through 0x70 */
  206.         2, 2, 2, 2, 1, 1, 2, 0        /* 0x80 through 0xf0 */
  207.     };
  208.     long lookfor, lng;
  209.     int c, c1, type;
  210.     int sysexcontinue = 0;    /* 1 if last message was an unfinished sysex */
  211.     int running = 0;    /* 1 when running status used */
  212.     int status = 0;        /* (possibly running) status byte */
  213.     int needed;
  214.  
  215.     if ( readmt("MTrk",0) == EOF )
  216.         return;
  217.  
  218.     Mf_toberead = read32bit();
  219.     Mf_currtime = 0;
  220.  
  221.     if ( Mf_starttrack )
  222.         (*Mf_starttrack)();
  223.  
  224.     while ( Mf_toberead > 0 ) {
  225.  
  226.         Mf_currtime += readvarinum();    /* delta time */
  227.  
  228.         c = egetc();
  229.  
  230.         if ( sysexcontinue && c != 0xf7 )
  231.             mferror("didn't find expected continuation of a sysex");
  232.  
  233.         if ( (c & 0x80) == 0 ) {     /* running status? */
  234.             if ( status == 0 )
  235.                 mferror("unexpected running status");
  236.             running = 1;
  237.         }
  238.         else {
  239.             status = c;
  240.             running = 0;
  241.         }
  242.  
  243.         needed = chantype[ (status>>4) & 0xf ];
  244.  
  245.         if ( needed ) {        /* ie. is it a channel message? */
  246.  
  247.             if ( running )
  248.                 c1 = c;
  249.             else
  250.                 c1 = egetc();
  251.             chanmessage( status, c1, (needed>1) ? egetc() : 0 );
  252.             continue;;
  253.         }
  254.  
  255.         switch ( c ) {
  256.  
  257.         case 0xff:            /* meta event */
  258.  
  259.             type = egetc();
  260.             /* watch out - Don't combine the next 2 statements */
  261.             lng = readvarinum();
  262.             lookfor = Mf_toberead - lng;
  263.             msginit();
  264.  
  265.             while ( Mf_toberead > lookfor )
  266.                 msgadd(egetc());
  267.  
  268.             metaevent(type);
  269.             break;
  270.  
  271.         case 0xf0:        /* start of system exclusive */
  272.  
  273.             /* watch out - Don't combine the next 2 statements */
  274.             lng = readvarinum();
  275.             lookfor = Mf_toberead - lng;
  276.             msginit();
  277.             msgadd(0xf0);
  278.  
  279.             while ( Mf_toberead > lookfor )
  280.                 msgadd(c=egetc());
  281.  
  282.             if ( c==0xf7 || Mf_nomerge==0 )
  283.                 sysex();
  284.             else
  285.                 sysexcontinue = 1;  /* merge into next msg */
  286.             break;
  287.  
  288.         case 0xf7:    /* sysex continuation or arbitrary stuff */
  289.  
  290.             /* watch out - Don't combine the next 2 statements */
  291.             lng = readvarinum();
  292.             lookfor = Mf_toberead - lng;
  293.  
  294.             if ( ! sysexcontinue )
  295.                 msginit();
  296.  
  297.             while ( Mf_toberead > lookfor )
  298.                 msgadd(c=egetc());
  299.  
  300.             if ( ! sysexcontinue ) {
  301.                 if ( Mf_arbitrary )
  302.                     (*Mf_arbitrary)(msgleng(),msg());
  303.             }
  304.             else if ( c == 0xf7 ) {
  305.                 sysex();
  306.                 sysexcontinue = 0;
  307.             }
  308.             break;
  309.         default:
  310.             badbyte(c);
  311.             break;
  312.         }
  313.     }
  314.     if ( Mf_endtrack )
  315.         (*Mf_endtrack)();
  316.     return;
  317. }
  318.  
  319. static VOID
  320. badbyte(c)
  321. int c;
  322. {
  323.     char buff[32];
  324.  
  325.     (VOID) sprintf(buff,"unexpected byte: 0x%02x",c);
  326.     mferror(buff);
  327. }
  328.  
  329. static VOID
  330. metaevent(type)
  331. {
  332.     int leng = msgleng();
  333.     char *m = msg();
  334.  
  335.     switch  ( type ) {
  336.     case 0x00:
  337.         if ( Mf_seqnum )
  338.             (*Mf_seqnum)(to16bit(m[0],m[1]));
  339.         break;
  340.     case 0x01:    /* Text event */
  341.     case 0x02:    /* Copyright notice */
  342.     case 0x03:    /* Sequence/Track name */
  343.     case 0x04:    /* Instrument name */
  344.     case 0x05:    /* Lyric */
  345.     case 0x06:    /* Marker */
  346.     case 0x07:    /* Cue point */
  347.     case 0x08:
  348.     case 0x09:
  349.     case 0x0a:
  350.     case 0x0b:
  351.     case 0x0c:
  352.     case 0x0d:
  353.     case 0x0e:
  354.     case 0x0f:
  355.         /* These are all text events */
  356.         if ( Mf_text )
  357.             (*Mf_text)(type,leng,m);
  358.         break;
  359.     case 0x2f:    /* End of Track */
  360.         if ( Mf_eot )
  361.             (*Mf_eot)();
  362.         break;
  363.     case 0x51:    /* Set tempo */
  364.         if ( Mf_tempo )
  365.             (*Mf_tempo)(to32bit(0,m[0],m[1],m[2]));
  366.         break;
  367.     case 0x54:
  368.         if ( Mf_smpte )
  369.             (*Mf_smpte)(m[0],m[1],m[2],m[3],m[4]);
  370.         break;
  371.     case 0x58:
  372.         if ( Mf_timesig )
  373.             (*Mf_timesig)(m[0],m[1],m[2],m[3]);
  374.         break;
  375.     case 0x59:
  376.         if ( Mf_keysig )
  377.             (*Mf_keysig)(m[0],m[1]);
  378.         break;
  379.     case 0x7f:
  380.         if ( Mf_sqspecific )
  381.             (*Mf_sqspecific)(leng,m);
  382.         break;
  383.     default:
  384.         if ( Mf_metamisc )
  385.             (*Mf_metamisc)(type,leng,m);
  386.     }
  387. }
  388.  
  389. static VOID
  390. sysex()
  391. {
  392.     if ( Mf_sysex )
  393.         (*Mf_sysex)(msgleng(),msg());
  394. }
  395.  
  396. static VOID
  397. chanmessage(status,c1,c2)
  398. int status;
  399. int c1, c2;
  400. {
  401.     int chan = status & 0xf;
  402.  
  403.     switch ( status & 0xf0 ) {
  404.     case NOTEOFF:
  405.         if ( Mf_off )
  406.             (*Mf_off)(chan,c1,c2);
  407.         break;
  408.     case NOTEON:
  409.         if ( Mf_on )
  410.             (*Mf_on)(chan,c1,c2);
  411.         break;
  412.     case PRESSURE:
  413.         if ( Mf_pressure )
  414.             (*Mf_pressure)(chan,c1,c2);
  415.         break;
  416.     case CONTROLLER:
  417.         if ( Mf_controller )
  418.             (*Mf_controller)(chan,c1,c2);
  419.         break;
  420.     case PITCHBEND:
  421.         if ( Mf_pitchbend )
  422.             (*Mf_pitchbend)(chan,c1,c2);
  423.         break;
  424.     case PROGRAM:
  425.         if ( Mf_program )
  426.             (*Mf_program)(chan,c1);
  427.         break;
  428.     case CHANPRESSURE:
  429.         if ( Mf_chanpressure )
  430.             (*Mf_chanpressure)(chan,c1);
  431.         break;
  432.     }
  433. }
  434.  
  435. /* readvarinum - read a varying-length number, and return the */
  436. /* number of characters it took. */
  437.  
  438. static long
  439. readvarinum()
  440. {
  441.     long value;
  442.     int c;
  443.  
  444.     c = egetc();
  445.     value = c;
  446.     if ( c & 0x80 ) {
  447.         value &= 0x7f;
  448.         do {
  449.             c = egetc();
  450.             value = (value << 7) + (c & 0x7f);
  451.         } while (c & 0x80);
  452.     }
  453.     return (value);
  454. }
  455.  
  456. static long
  457. to32bit(c1,c2,c3,c4)
  458. {
  459.     long value = 0L;
  460.  
  461.     value = (c1 & 0xff);
  462.     value = (value<<8) + (c2 & 0xff);
  463.     value = (value<<8) + (c3 & 0xff);
  464.     value = (value<<8) + (c4 & 0xff);
  465.     return (value);
  466. }
  467.  
  468. static
  469. to16bit(c1,c2)
  470. int c1, c2;
  471. {
  472.     return ((c1 & 0xff ) << 8) + (c2 & 0xff);
  473. }
  474.  
  475. static long
  476. read32bit()
  477. {
  478.     int c1, c2, c3, c4;
  479.  
  480.     c1 = egetc();
  481.     c2 = egetc();
  482.     c3 = egetc();
  483.     c4 = egetc();
  484.     return to32bit(c1,c2,c3,c4);
  485. }
  486.  
  487. static int
  488. read16bit()
  489. {
  490.     int c1, c2;
  491.     c1 = egetc();
  492.     c2 = egetc();
  493.     return to16bit(c1,c2);
  494. }
  495.  
  496. static VOID
  497. mferror(s)
  498. char *s;
  499. {
  500.     if ( Mf_error )
  501.         (*Mf_error)(s);
  502.     exit(1);
  503. }
  504.  
  505. /* The code below allows collection of a system exclusive message of */
  506. /* arbitrary length.  The Msgbuff is expanded as necessary.  The only */
  507. /* visible data/routines are msginit(), msgadd(), msg(), msgleng(). */
  508.  
  509. #define MSGINCREMENT 128
  510. static char *Msgbuff = 0;    /* message buffer */
  511. static int Msgsize = 0;        /* Size of currently allocated Msg */
  512. static int Msgindex = 0;    /* index of next available location in Msg */
  513.  
  514. static VOID
  515. msginit()
  516. {
  517.     Msgindex = 0;
  518. }
  519.  
  520. static char *
  521. msg()
  522. {
  523.     return(Msgbuff);
  524. }
  525.  
  526. static int
  527. msgleng()
  528. {
  529.     return(Msgindex);
  530. }
  531.  
  532. static VOID
  533. msgadd(c)
  534. int c;
  535. {
  536.     /* If necessary, allocate larger message buffer. */
  537.     if ( Msgindex >= Msgsize )
  538.         msgenlarge();
  539.     Msgbuff[Msgindex++] = c;
  540. }
  541.  
  542. static VOID
  543. msgenlarge()
  544. {
  545.     char *newmess;
  546.     char *oldmess = Msgbuff;
  547.     int oldleng = Msgsize;
  548.     char *malloc();
  549.  
  550.     Msgsize += MSGINCREMENT;
  551.     newmess = malloc( (unsigned)(sizeof(char)*Msgsize) );
  552.  
  553.     /* copy old message into larger new one */
  554.     if ( oldmess != 0 ) {
  555.         register char *p = newmess;
  556.         register char *q = oldmess;
  557.         register char *endq = &oldmess[oldleng];
  558.  
  559.         for ( ; q!=endq ; p++,q++ )
  560.             *p = *q;
  561.         free(oldmess);
  562.     }
  563.     Msgbuff = newmess;
  564. }
  565.